package com.jake.xfeed.recyclerfeed.pager;

import android.util.Log;
import android.util.SparseArray;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class PageChangedHelper extends RecyclerView.OnScrollListener {

    private static final String TAG = "PageChangedHelper";
    private OnPageChangedListeners mOnPageChangedListeners = new OnPageChangedListeners();
    @NonNull
    private LinearLayoutManager mLayoutManager;
    private int mPosition = -1;
    private int mScrollDistance = 0;


    public PageChangedHelper(@NonNull LinearLayoutManager layoutManager) {
        mLayoutManager = layoutManager;

    }

    private int mNextPosition = 0;

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        Log.d(TAG, "onScrolled  dx=" + dx + "   dy=" + dy);
        int scrollDistance = mLayoutManager.getOrientation() == LinearLayoutManager.VERTICAL ? dy : dx;
        int targetTotalScroll = mScrollDistance + scrollDistance;
        int nextPosition = targetTotalScroll > 0 ? mPosition + 1 : mPosition - 1;
        if (targetTotalScroll == 0) {
            nextPosition = mNextPosition;
        } else {
            mNextPosition = nextPosition;
        }

        int totalItem = recyclerView.getAdapter() != null ? recyclerView.getAdapter().getItemCount() : 0;
        if (nextPosition > totalItem - 1) {
            nextPosition = totalItem - 1;
        } else if (nextPosition < 0) {
            nextPosition = 0;
        }
        if (mPosition != nextPosition) {
            View view = mLayoutManager.findViewByPosition(mPosition);
            if (view != null) {
                int totalScrollPx = mLayoutManager.getOrientation() == LinearLayoutManager.VERTICAL ? view.getHeight() : view.getWidth();
                if (targetTotalScroll > totalScrollPx) {
                    targetTotalScroll = totalScrollPx;
                }
                float percent = targetTotalScroll * 1f / totalScrollPx;
                mOnPageChangedListeners.onPageScrolled(mPosition, nextPosition, percent, targetTotalScroll);
            }
        }
        mScrollDistance = targetTotalScroll;

    }

    public void customPageSelected(int position) {
        if (mPosition != position) {
            mOnPageChangedListeners.onPageSelected(mPosition, position);
            mPosition = position;
        }
    }

    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            View view = mLayoutManager.findViewByPosition(mPosition);
            Log.e(TAG, "onScrollStateChanged  newState=" + newState + "  mScrollDistance=" + mScrollDistance + "   mPosition=" + mPosition);
            if (view != null) {
                int absScrollDistance = Math.abs(mScrollDistance);
                if (absScrollDistance > 0 && absScrollDistance < view.getWidth()) {
                    return;
                }
            }
            int position = mLayoutManager.findFirstVisibleItemPosition();
            if (mPosition != position) {
                mOnPageChangedListeners.onPageSelected(mPosition, position);
                mPosition = position;
            }
        } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
            mScrollDistance = 0;
        }
        mOnPageChangedListeners.onPageScrollStateChanged(newState);
    }

    public void addOnPageChangedListener(RecyclerViewPageFeed.OnPageChangedListener listener) {
        mOnPageChangedListeners.add(listener);
    }

    public void removeOnPageChangedListener(RecyclerViewPageFeed.OnPageChangedListener listener) {
        mOnPageChangedListeners.remove(listener);
    }

    private static class OnPageChangedListeners implements RecyclerViewPageFeed.OnPageChangedListener {
        private SparseArray<RecyclerViewPageFeed.OnPageChangedListener> mListeners = new SparseArray<>();

        void add(RecyclerViewPageFeed.OnPageChangedListener listener) {
            if (listener != null) {
                mListeners.put(listener.hashCode(), listener);
            }
        }

        void remove(RecyclerViewPageFeed.OnPageChangedListener listener) {
            if (listener != null) {
                mListeners.remove(listener.hashCode());
            }
        }

        @Override
        public void onPageScrolled(int lastPosition, int position, float positionOffset, int positionOffsetPixels) {
            callback(new IListenerTask<RecyclerViewPageFeed.OnPageChangedListener>() {
                @Override
                public void run(@NonNull RecyclerViewPageFeed.OnPageChangedListener listener) {
                    listener.onPageScrolled(lastPosition, position, positionOffset, positionOffsetPixels);
                }
            });
        }

        @Override
        public void onPageSelected(int lastPosition, int position) {
            callback(new IListenerTask<RecyclerViewPageFeed.OnPageChangedListener>() {
                @Override
                public void run(@NonNull RecyclerViewPageFeed.OnPageChangedListener listener) {
                    listener.onPageSelected(lastPosition, position);
                }
            });
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            callback(new IListenerTask<RecyclerViewPageFeed.OnPageChangedListener>() {
                @Override
                public void run(@NonNull RecyclerViewPageFeed.OnPageChangedListener listener) {
                    listener.onPageScrollStateChanged(state);
                }
            });
        }

        private void callback(IListenerTask<RecyclerViewPageFeed.OnPageChangedListener> task) {
            for (int i = 0; i < mListeners.size(); i++) {
                int key = mListeners.keyAt(i);
                RecyclerViewPageFeed.OnPageChangedListener listener = mListeners.get(key);
                if (listener != null) {
                    task.run(listener);
                }
            }
        }
    }

    public static interface IListenerTask<Listener> {
        void run(@NonNull Listener listener);
    }
}
